一句话结论

对于大多数 Web 应用,Access Token + Refresh Token 双 Token 是更常见、也更实用的登录态管理方案。

前端使用公私钥进行身份认证,并不是双 Token 的替代品。它解决的是“客户端如何证明自己持有某个密钥”,而双 Token 解决的是“访问凭证如何使用、续期和失效”。两者可以结合使用,但不能简单地认为公私钥方案一定更安全。

如果需要使用公私钥,通常应优先考虑 WebAuthn/Passkey 等成熟标准,而不是自行设计前端加密协议。


什么是双 Token?

双 Token 通常指:

  • Access Token(访问令牌):用于访问业务 API,有效期较短。

  • Refresh Token(刷新令牌):用于在 Access Token 过期后换取新的访问令牌,有效期较长。

典型流程如下:

        
用户登录
  ↓
服务端签发 Access Token + Refresh Token
  ↓
前端使用 Access Token 请求 API
  ↓
Access Token 过期
  ↓
前端使用 Refresh Token 请求刷新接口
  ↓
服务端验证后签发新的 Token
        
      

双 Token 的关键价值,是把“频繁使用的访问凭证”和“用于续期的长期凭证”分开管理。

常见存储方式

浏览器应用通常需要谨慎处理 Token 存储:

  • 将 Refresh Token 放在 HttpOnly、Secure、SameSite Cookie 中,可以降低它被 JavaScript 直接读取的风险。

  • Access Token 可以采用短生命周期,并尽量减少其暴露范围。

  • 使用 Cookie 时,还要考虑 CSRF 防护;使用 Bearer Token 时,则要重点防范 XSS 导致的 Token 窃取。

具体存储方式应结合前端架构、跨域配置、CSRF 防护和后端认证设计确定,不存在适用于所有项目的单一方案。


什么是前端使用 Crypto 公私钥鉴权换 Token?

这种方案通常指客户端生成或持有一对密钥:

  • 公钥:提交给服务端保存,或在注册时绑定到用户身份。

  • 私钥:由客户端持有,用于对服务端发起的随机挑战进行签名。

  • 服务端:使用公钥验证签名,验证通过后再签发 Token。

简化流程如下:

        
客户端发起认证
  ↓
服务端返回随机挑战值
  ↓
客户端使用私钥对挑战值签名
  ↓
服务端使用对应公钥验证签名
  ↓
验证通过后签发 Token
        
      

这种方式的核心不是“用公钥加密、私钥解密来登录”,而通常是使用私钥签名,服务端用公钥验签。认证过程还必须设计好随机挑战、有效期、一次性使用、用户与公钥绑定等机制,避免重放攻击。


双 Token 与公私钥鉴权对比

对比项

双 Token

前端公私钥鉴权

主要解决的问题

API 访问、续期与登录态管理

证明客户端持有对应私钥

是否需要服务端状态

视实现而定;Refresh Token 通常需要可撤销管理

通常需要保存公钥、设备或凭证绑定关系

前端实现复杂度

低到中

中到高

后端实现复杂度

低到中

中到高

凭证被盗后的风险

取决于 Token 生命周期、存储和撤销机制

私钥不易导出时风险可降低,但仍要考虑恶意代码调用

适用场景

大多数网站、管理后台、移动应用 API

设备绑定、无密码登录、高安全认证、客户端持有密钥的场景

能否取代另一方

不适用

通常不能完全取代 Token 生命周期管理

需要注意:公私钥鉴权通常只解决“如何完成认证”,认证通过后服务端仍可能签发 Access Token、Refresh Token 或其他会话凭证。因此,公私钥鉴权与双 Token 可以组合使用。


哪种方案更安全?

安全性不能只看“用了加密算法”或“用了公私钥”,还要看密钥存储、攻击面和整个认证流程。

双 Token 的主要风险

双 Token 方案需要重点防范:

  1. XSS 攻击:恶意脚本可能读取前端可访问的 Token,或冒用当前页面的用户权限。

  2. Refresh Token 泄露:长期有效的刷新凭证一旦被盗,可能被用于持续换取新令牌。

  3. 重放与滥用:旧的 Refresh Token 如果没有轮换、撤销和异常检测机制,风险会增大。

  4. CSRF 攻击:如果认证凭证通过 Cookie 自动携带,需要设计相应的 CSRF 防护。

常见防护措施包括:短有效期 Access Token、Refresh Token 轮换、服务端撤销机制、异常登录检测、严格的 Cookie 配置以及完善的 XSS 防护。

前端私钥并不天然安全

很多团队会误以为“私钥放在浏览器里,就比 Token 安全”。这并不总是成立。

即使通过 Web Crypto API 生成不可导出的私钥,恶意脚本也可能在页面运行期间调用签名能力。不可导出可以降低密钥被复制的风险,但不能保证密钥不会被滥用。

此外,如果私钥以字符串形式写在前端代码、配置文件或静态资源中,那么它本质上是公开信息。浏览器代码最终会发送给用户,不能把前端内置的私钥当作服务器秘密。

如果需要在客户端使用密钥,应考虑:

  • 使用 WebAuthn/Passkey 等成熟标准;

  • 尽可能让私钥由平台安全硬件或系统凭证管理器保护;

  • 使用服务端随机挑战,防止签名被重放;

  • 设计密钥撤销、设备解绑和丢失后的恢复流程;

  • 避免自行发明密码学协议。


应该怎么选?

选择双 Token 的场景

如果你正在开发以下系统,通常可以优先从双 Token 方案开始:

  • 普通 Web 网站;

  • SaaS 产品;

  • 企业管理后台;

  • 前后端分离的业务系统;

  • 需要让 API 客户端携带访问凭证的应用。

双 Token 的生态成熟、团队容易理解,也方便与 JWT、OAuth 2.0、OIDC 等方案结合。关键是正确设计 Token 生命周期和存储方式,而不是单纯追求复杂的加密流程。

考虑公私钥认证的场景

以下情况可以考虑公私钥认证,或直接采用 WebAuthn/Passkey:

  • 希望提供无密码登录;

  • 需要绑定可信设备;

  • 有较高的身份认证安全要求;

  • 客户端具备可靠的密钥保护能力;

  • 需要通过签名证明客户端持有某个密钥。

但要注意:采用公私钥认证后,仍需要解决会话管理、Token 续期、用户退出、设备丢失和凭证吊销等问题。

可以组合使用

一种常见的组合方式是:

        
WebAuthn/公私钥完成用户认证
  ↓
服务端验证身份
  ↓
服务端签发短期 Access Token 和 Refresh Token
  ↓
客户端按双 Token 机制访问 API 和续期
        
      

这样,公私钥用于加强登录认证,双 Token 用于管理登录后的 API 会话。两者职责清晰,不必二选一。


推荐方案

对于大多数 Web 项目,可以参考以下设计原则:

  1. 使用成熟的认证标准,避免自行设计签名和换 Token 协议。

  2. Access Token 使用较短有效期,降低泄露后的可利用时间。

  3. Refresh Token 做轮换和撤销管理,并检测异常重复使用。

  4. 不要把服务器私钥或长期密钥写进前端代码。

  5. 根据架构选择安全的凭证存储方式,并同时防护 XSS 和 CSRF。

  6. 高安全登录需求优先评估 WebAuthn/Passkey,不要仅因为使用 Crypto 就认为方案安全。

  7. 将认证与会话管理分开设计:认证成功不代表后续 Token 生命周期问题已经解决。


常见问题 FAQ

1. 前端生成密钥后,私钥可以安全地放在浏览器吗?

不能简单地认为安全。Web Crypto API 可以支持不可导出的密钥,但恶意脚本仍可能在页面运行时调用密钥完成签名。还需要结合 XSS 防护、设备安全能力和完整的密钥生命周期管理。

2. 公私钥鉴权后,还需要 Refresh Token 吗?

不一定,但通常仍需要某种会话续期机制。公私钥认证负责证明身份或持有凭证,Refresh Token 负责续期;二者解决的问题不同。

3. JWT 是不是双 Token?

不是。JWT 是一种令牌格式;双 Token 是一种令牌管理方式。Access Token 和 Refresh Token 可以使用 JWT,也可以使用服务端生成的随机不透明字符串。

4. 前端使用 AES 加密密码后发送,是否更安全?

不一定。客户端加密并不能替代 HTTPS,也不能解决恶意脚本、密钥管理或重放问题。密码传输应使用 HTTPS,并采用成熟的认证协议和服务端密码存储方案。


总结

双 Token 更适合解决日常 API 访问和登录态续期问题;公私钥鉴权更适合证明客户端持有密钥,或实现设备绑定、无密码登录等认证能力。

因此,大多数项目不需要在两者之间做绝对二选一。更合理的做法是:先采用成熟的 Token 会话管理方案;如果确实有更高的认证安全需求,再结合 WebAuthn/Passkey 或经过标准化设计的公私钥认证。

最重要的是,前端代码无法保守服务器秘密,Crypto 也不能自动保证系统安全。最终安全性取决于密钥管理、Token 生命周期、浏览器攻击面和完整的认证流程设计。